
#include "game.h"
#include "DllLoader.h"
#pragma comment (lib,"NBE.lib")


#include "Vertex.h"
#define NBE_FLOAT 0x1406

#include "Mouse.h"
#include "KeyBoard.h"

#include "CustomEvent.h"


#include <boost/bind.hpp>

#define CURRENTTIME (microsec_clock::universal_time()- startpt).total_milliseconds();


using namespace NBE;
namespace NOEXIT
{
	RenderInfo* Game::loadRenderInfo(wchar_t* cfgname)
	{
		cfg.loadConfig(cfgname);
		//cfg.load(iniName);
		RenderInfo* rdinfo = new RenderInfo();
		rdinfo->height = TypeCast::stringToInt( cfg.getInfo("height") );
		rdinfo->width = TypeCast::stringToInt( cfg.getInfo("width") );
		rdinfo->fullScreen = TypeCast::charToBool( cfg.getInfo("fullScreen").c_str() );
		string str = cfg.getInfo("renderSystem");
		if(str == string("GL"))
		{
			rdinfo->type = 0;
		}
		//get the wchar_t str to initialize window
		str = cfg.getInfo("title");
		wchar_t* w_str = TypeCast::charToWchar(str.c_str());
		size_t w_len = str.size();
		wcscpy_s(rdinfo->title,w_len+1,w_str);
		delete w_str;

		str = cfg.getInfo("className");
		w_str = TypeCast::charToWchar(str.c_str());
		w_len = str.size();
		wcscpy_s(rdinfo->className,w_len+1,w_str);
		delete w_str;

		return rdinfo;
	}
	Game::Game(HINSTANCE h)
		:rtt(0),localGuarantee(0),serverGuarantee(0),GuaranteeSendFlag(false),
		 sendMove(0),
		 lastTimeSendMove(0),
		 rttCheckNow(0),
		 lastTimeRttCheck(0),
		 sendNow(0),
		 lastTimeSend(0),
		 sendGuaranteeNow(0),
		 lastTimeGuarantee(0),
		 m_timer(Time()),
		 m_nextUpdateTime(0),
		 m_startFrameTime(0)
	{
		
		RenderInfo* rdinfo = loadRenderInfo(L"config.ini");
		if(rdinfo->type == 0)
		{
			rdinfo->type = 0;	 
		}
		
		/*DllLoader loader;
		loader.load(L"RendererGL.dll");
		typedef RenderSystem* (__cdecl* createGLfuncPointer)(RenderInfo*, HINSTANCE);
		createGLfuncPointer ptr_GL;
		ptr_GL = (createGLfuncPointer)loader.getProcAddress("createGL");
		m_pRenderer.reset( ptr_GL(rdinfo,h));*/
		

		HINSTANCE m_rendererDLL = LoadLibrary(L"RendererGL.dll");
		typedef RenderSystem* (__cdecl* createGLfuncPointer)(RenderInfo*, HINSTANCE);
		createGLfuncPointer ptr_GL;
		ptr_GL = (createGLfuncPointer)GetProcAddress(m_rendererDLL,"createGL");
		m_pRenderer.reset( ptr_GL(rdinfo,h));
		 
		textureMgr = TextureManager::getInstancePtr();
		textureMgr->initialize(m_pRenderer.get());
		textureMgr->LoadFromFile(L"Resources\\default-alpha.png");
		shaderMgr = ShaderManager::getInstancePtr();
		shaderMgr->initialize(m_pRenderer.get());


		initInfo.sizeX = 1024;
		initInfo.sizeZ = 1024;
		//camera
		m_pCamera.reset(new Camera());
		float asp = static_cast<float>(rdinfo->width)/rdinfo->height;
		m_pCamera->setPosition(vec3f(float(initInfo.sizeX/2),1200.0f,float(initInfo.sizeZ/2)));
		m_pCamera->updateViewMatrix();
		m_pCamera->setProjection(45.0f,asp,0.1f,10000.0f);
		m_pCamera->rotate(vec3f(-90,0,0));
		m_pCamera->applyImpulse(vec3f());
		
		//control
		Mouse* mouse = new Mouse();
		mouse->calculateCenter( m_pRenderer->getWindow()->getHWND());
		mouse->registerListener(this);
		KeyBoard* keyboard = new KeyBoard();
		keyboard->registerListener(this);
		m_inputVec.push_back(mouse);
		m_inputVec.push_back(keyboard);
		m_pRenderer->getWindow()->RegisterInputs(&m_inputVec);

		//temp data
		currentState = INITMAP;//CONNECT;
		currentPlayer = new Player();
		createPlayerRO( currentPlayer );
		playerList.push_back(currentPlayer);



		
	}

	Game::~Game()
	{
		textureMgr->deleteInstance();
		shaderMgr->deleteInstance();

		delete map;

		for(auto it = playerList.begin(); it!=playerList.end();)
		{
			delete *it;
			it = playerList.erase(it);
		}

		for(auto it = bulletList.begin(); it!=bulletList.end();)
		{
			delete *it;
			it = bulletList.erase(it);
		}
		
		for(auto it = m_inputVec.begin(); it!=m_inputVec.end();)
		{
			delete *it;
			it = m_inputVec.erase(it);
		}
		
		//last msg
		SMsg msg;
		msg.msgId = LOGOUT;
		msg.sessionId = sessionId;
		NeedToSend.push_back(msg);
		startSend();
		deleteNetwork();
	}


	void Game::run()
	{
		//msg
		bool gotMsg;
		MSG  msg;

		::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE);

		while (WM_QUIT != msg.message)
		{
			//if (m_pRenderer->isActive())
			{
				gotMsg = ::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) ? true : false;
			}
			//else
			//{
			//	gotMsg = ::GetMessage(&msg, NULL, 0, 0) ? true : false;
			//}

			if (gotMsg)
			{
				::TranslateMessage(&msg);
				::DispatchMessage(&msg);
			}
			else
			{
				if(currentState != QUIT)
					updateFrame();
				
			}

		}
		
	}

	void Game::updateFrame()
	{
		m_startFrameTime = m_timer.GetSystemClocks();
		m_timer.PreciseWaitUntill(m_nextUpdateTime);
		m_nextUpdateTime = m_timer.GetSystemClocks()  + m_timer.getDesireColocsPerFrame();

		service.poll();

		if (m_pRenderer->isActive())
		{
			std::for_each(begin(m_inputVec),end(m_inputVec),[&](Input* input){
				input->update();//read events
				input->handleAllEvents();
			});
		}

		m_pCamera->updateViewMatrix();

		float color[4] = {0.5f,0.6f,0.7f,0.1f}; 
		m_pRenderer->clearColorBuffer(color);
		m_pRenderer->clearDepthBuffer(1);
		
		//build buffer for rendering
		//render in update

		switch(currentState)
		{
		case INITMAP:
			initMap();
			login();
			break;
		case INGAME:
			{
				//tell server i am here
				sendMove = CURRENTTIME
					if(sendMove - lastTimeSendMove > 16 && currentPlayer->getVel().length() > 0.1f)
				{
					lastTimeSendMove=  sendMove;
					if(sessionId > -1)
					{
						SMsg msg;
						msg.msgId = PLAYERMOVE;
						msg.sessionId = sessionId;
						memcpy_s(msg.data,sizeof(PlayerInfo),&currentPlayer->getPlayerInfo(),sizeof(PlayerInfo));
						NeedToSend.push_back(msg);
					}
				}
				

			//map
				m_pRenderer->applyShader(map->shader);
				m_pRenderer->applyMatrix(map->shader,"viewMat",m_pCamera->getViewMatrix());
				m_pRenderer->applyMatrix(map->shader,"projMat",m_pCamera->getProjection());
				m_pRenderer->applyTexture(map->shader, "diftex", map->texId,0);
				m_pRenderer->bindVertexBuffer(map->vbo_id,sizeof(Vertex),0, ShaderManager::getInstancePtr()->getShaderByIdx(map->shader) );
				m_pRenderer->bindIndexBuffer(map->ibo_id);
	
				drawRO(map,Matrix4f::Identity());
				
			//player
				for(auto it =playerList.begin(); it!= playerList.end(); ++it)
				{
					RenderObject* ro = (*it)->getRenderObjcet();
					m_pRenderer->applyShader(ro->shader);
					m_pRenderer->applyMatrix(ro->shader,"viewMat",m_pCamera->getViewMatrix());
					m_pRenderer->applyMatrix(ro->shader,"projMat",m_pCamera->getProjection());
					m_pRenderer->applyTexture(ro->shader, "diftex", ro->texId,0);
					m_pRenderer->bindVertexBuffer(ro->vbo_id,sizeof(Vertex),0, ShaderManager::getInstancePtr()->getShaderByIdx(map->shader) );
					m_pRenderer->bindIndexBuffer(ro->ibo_id);

					(*it)->updatePos();
					Matrix4f playerWmat = (*it)->getPosMat();
					drawRO(ro,playerWmat);
				}

				for(auto it =bulletList.begin(); it!= bulletList.end(); ++it)
				{
					RenderObject* ro = (*it)->getRenderObjcet();
					m_pRenderer->applyShader(ro->shader);
					m_pRenderer->applyMatrix(ro->shader,"viewMat",m_pCamera->getViewMatrix());
					m_pRenderer->applyMatrix(ro->shader,"projMat",m_pCamera->getProjection());
					m_pRenderer->applyTexture(ro->shader, "diftex", ro->texId,0);
					m_pRenderer->bindVertexBuffer(ro->vbo_id,sizeof(Vertex),0, ShaderManager::getInstancePtr()->getShaderByIdx(map->shader) );
					m_pRenderer->bindIndexBuffer(ro->ibo_id);

					(*it)->updatePos();
					Matrix4f bulletWmat = (*it)->getPosMat();
					drawRO(ro,bulletWmat);
				}
				m_pCamera->setPosition(currentPlayer->getPos() + vec3f(0,500,0));

				


				m_pRenderer->swapBuff(true);
			}
			break;
		case QUIT:
			break;
		}


					//for rtt check 

			rttCheckNow = CURRENTTIME
			if( rttCheckNow - lastTimeRttCheck> 1000)
			{
				SMsg msg;
				lastTimeRttCheck = rttCheckNow;
				msg.msgId = RTT;	
				msg.time = rttCheckNow;
				msg.sessionId = sessionId;
				NeedToSend.push_back(msg);
			}


			//send guarantee
			sendGuaranteeNow = CURRENTTIME
			if(GuaranteeSendFlag || sendGuaranteeNow - lastTimeGuarantee > 1000)
			{
				lastTimeGuarantee = sendGuaranteeNow;
				startSend_Guarantee();
				GuaranteeSendFlag = false;
			}

			sendNow = CURRENTTIME
			//send msgs based on rtt
			if(sendNow - lastTimeSend >= rtt/2)
			{
				lastTimeSend = sendNow;
				//checkHeartBeat();
				startSend();
			}

				
	}


	void Game::initMap()
	{
		map = new RenderObject();
		map->vbo.push_back( Vertex(vec3f(0,0,float(initInfo.sizeZ)),vec3f(0,1,0),vec4f(),vec2f(0,0)));
		map->vbo.push_back( Vertex(vec3f(float(initInfo.sizeX),0,float(initInfo.sizeZ)),vec3f(0,1,0),vec4f(),vec2f(1,0)));
		map->vbo.push_back( Vertex(vec3f(float(initInfo.sizeZ),0,0),vec3f(0,1,0),vec4f(),vec2f(1,1)));
		map->vbo.push_back( Vertex(vec3f(0,0,0),vec3f(0,1,0),vec4f(),vec2f(0,1)));

		map->ibo.push_back(0);map->ibo.push_back(1);map->ibo.push_back(2);
		map->ibo.push_back(2);map->ibo.push_back(3);map->ibo.push_back(0);

		generalShader = map->shader = shaderMgr->loadShader(L"Shader\\general");
			 
		Shader* sd = ShaderManager::getInstancePtr()->getShaderByIdx(generalShader);
		sd->addAttributes(POS,3,NBE_FLOAT);
		sd->addAttributes(TEXCOORD0,2,NBE_FLOAT);
		sd->addAttributes(NORMAL,3,NBE_FLOAT);
		sd->addAttributes(COLOR,4,NBE_FLOAT);


		map->texId = textureMgr->LoadFromFile(L"Resources\\darktile.jpg")->textureIdx;
		
		m_pRenderer->createVBO(map,sizeof(Vertex),map->shader,"PTNC");
		m_pRenderer->createIBO(map);
		
	}

	void Game::initNetwork()
	{
		server_address = ip::udp::endpoint(ip::address::from_string(cfg.getInfo("serverIP")),
		2733);

		ip::udp::endpoint my_address(ip::address::address(),0);
		mySocket = new ip::udp::socket(service, my_address); 
		startReceive();
	}

	void Game::deleteNetwork()
	{
		delete mySocket;
	}
	void Game::login()
	{
		initNetwork();
		startpt = microsec_clock::universal_time();

		SMsg msg;
		msg.msgId = LOGIN;
		msg.guarantee = true;
		msg.msgOrder = ++localGuarantee;
		msg.sessionId = -1;
		NeedToSend_Guarantee.push_back(msg);
		GuaranteeSendFlag = true;
		currentState = INGAME;
	}

	void Game::drawRO(RenderObject* ro, Matrix4f& worldMat)
	{
		m_pRenderer->applyMatrix(ro->shader,"modelMat",worldMat);
		m_pRenderer->drawIndex(4,ro->ibo.size(),0,0);//4 == triangles

	}

	void Game::handleEvent(Event* e)
	{
		switch(e->type)
		{
		//case MOUSE_MOVE:
		//	currentPlayer->rotate(static_cast<MouseEvent*>(e)->deltaMove);
		//	currentPlayer->applyImpulse(vec3f());//apply the rotation only
		//	break;
		//case MOUSE_BUTTONDOWN:
		//	break;
		//case MOUSE_BUTTON_PRESS:
		//	break;
		//case MOUSE_BUTTON_RELEASE:
		//	break;
		//	//key
		case KEY_RELEASE:
			handleKeyRelease(static_cast<KeyEvent*>(e)->virtualKey);
			break;
		//case KEY_PRESS:
		//	break;
		case KEY_DOWN:
			handleKeyDown(static_cast<KeyEvent*>(e)->virtualKey);
			break;
		}
	}
	void Game::handleKeyDown(int key)
	{
		vec3f impuse;
		vec3f rot;
		switch(key)
		{
		case 'W':impuse.z -= .5f;break;
		case 'S':impuse.z += .5f;break;
		case 'A':impuse.x -= .5f;break;
		case 'D':impuse.x += .5f;break;
		case 'J':rot.y -= 10;break;
		case 'K':rot.y += 10;break;
		}
		currentPlayer->rotate(rot);
		currentPlayer->applyImpulse(impuse);
	}
	void Game::handleKeyRelease(int key)
	{
		switch(key)
		{
		case VK_SPACE:
			shoot(currentPlayer);
			break;
		}
	}
	//
	void Game::startSend()
	{
		for(unsigned int i=0;i<NeedToSend.size();i++)
		{
			memcpy_s(byteData,sizeof(SMsg),&NeedToSend[i],sizeof(SMsg));
			mySocket->async_send_to(buffer(byteData,sizeof(SMsg)),server_address,
				boost::bind(&Game::SendMsgHandler,this,
				boost::asio::placeholders::error,
				boost::asio::placeholders::bytes_transferred)
				);
		}
		NeedToSend.clear(); 
	}
	void Game::startSend_Guarantee()
	{
		for(auto it=NeedToSend_Guarantee.begin();
			it!=NeedToSend_Guarantee.end();it++)
		{
			//trace("sending guarantee msgs order"<<(*it).msgOrder);
			memcpy_s(byteData,sizeof(SMsg),&(*it),sizeof(SMsg));
			mySocket->async_send_to(buffer(byteData,sizeof(SMsg)),server_address,
				boost::bind(&Game::SendMsgHandler,this,
				boost::asio::placeholders::error,
				boost::asio::placeholders::bytes_transferred)
				);
		}
	}
	void Game::startReceive()
	{
		mySocket->async_receive_from(buffer(rcvByteData,BUFFSIZE),server_address,
			boost::bind(&Game::MsgHandler,this,
			boost::asio::placeholders::error,
			boost::asio::placeholders::bytes_transferred)
			);
	}
	void Game::receiver()
	{}
	void Game::keepalive()
	{}

	void Game::MsgHandler(const boost::system::error_code& ec,std::size_t bytes_transferred)
	{
		if(ec.value()!=0)
		{
			currentState = QUIT;
			MessageBox(nullptr,L"network error",L"error",MB_OK|MB_ICONERROR);
			return;
		}
		SMsg* receivedMsg =  reinterpret_cast<SMsg*>(rcvByteData);
		switch(receivedMsg->msgId)
		{
		case LOGIN_SUCCEED:
			//trace("succeed! this session id = "<<receivedMsg->sessionId);
			sessionId = receivedMsg->sessionId;
			currentPlayer->setPlayerId(sessionId);
			currentPlayer->setPlayerInfo(reinterpret_cast<PlayerInfo*>(receivedMsg->data));
			break;
		case RTT_SUCCEED:
			{ 
				//std::cout<<"succeed! rtt returned\n";
				long long nowTime= CURRENTTIME//clock();
					rtt = long long (rtt * 0.2f + 0.8f *(nowTime - receivedMsg->time));
			//	trace("rtt is "<<rtt);
			}
			break;
		case UPDATEPLAYERS:
			{
				updatePlayers(receivedMsg->dataSize, reinterpret_cast<PlayerInfo*>(receivedMsg->data));

			}
			break;
		case PLAYERLEAVE:
			{
				int pid = reinterpret_cast<PlayerInfo*>(receivedMsg->data)->playerId;
				removePlayerById(pid);
			}
			break;
		case RESETPLAYER:
			{
				PlayerInfo* pinfo = reinterpret_cast<PlayerInfo*>(receivedMsg->data);
				int pid = pinfo->playerId;
				Player* p = getPlayerById(pid);
				p->setPlayerInfo(pinfo);
			}
			break;
		case ADDBULLET:
			{
				addBullet(reinterpret_cast<BulletInfo*>(receivedMsg->data));
			}
			break;
		case REMOVEBULLET:
			{
				removeBullet(reinterpret_cast<BulletInfo*>(receivedMsg->data));
			}
			break;
		case ACK:
			clearGuaranteeMsgs(receivedMsg->msgOrder);
			break;
		}

		if(receivedMsg->guarantee)
		{
			std::cout<<"get server'msg order:"<<receivedMsg->msgOrder<<" sessionOrder:"<<serverGuarantee<<"\n";

			if(  receivedMsg->msgOrder <= serverGuarantee + 1
				)
			{
				SMsg ackMsg;
				ackMsg.msgId = ACK;
				std::cout<<"ack: "<<receivedMsg->msgOrder<<std::endl;
				ackMsg.msgOrder = receivedMsg->msgOrder;
				ackMsg.sessionId = sessionId;
				NeedToSend.push_back(ackMsg);

				if(receivedMsg->msgOrder - serverGuarantee == 1)
					serverGuarantee += 1;
			}

		}

		startReceive();
	}
	void Game::SendMsgHandler(const boost::system::error_code& ec,std::size_t bytes_transferred)
	{
		if(ec.value()!=0)
		{
			currentState = QUIT;
			MessageBox(nullptr,L"network error",L"error",MB_OK|MB_ICONERROR);
			return;
		}
	}
	void Game::clearGuaranteeMsgs(long long msgOrder)
	{
		auto it = NeedToSend_Guarantee.begin();
		for(;it!=NeedToSend_Guarantee.end();)
		{
			if((*it).msgOrder <= msgOrder)
			{
				//trace("delete order "<<(*it).msgOrder);
				it = NeedToSend_Guarantee.erase(it);
			}
			else
			{
				++it;
			}
		}
	}

	//logic
	void Game::updatePlayers(int num, PlayerInfo* parray)
	{
		for(int i =0; i< num; ++i)
		{
			PlayerInfo* pinfo = parray + i;

			if(pinfo->playerId == currentPlayer->getPlayerId())
				continue;
			Player* p = getPlayerById(pinfo->playerId);
			if(!p)
			{
				//new player haha
				p = new Player();
				createPlayerRO(p);
				playerList.push_back(p);
			}
			p->setPlayerInfo(pinfo);
		}
	}
	Player* Game::getPlayerById(int id)
	{
		for(auto it = playerList.begin(); it!= playerList.end();++it)
		{
			if((*it)->getPlayerId() == id)
				return *it;
		}
		return nullptr;
	}
	void Game::removePlayerById(int id)
	{
		for(auto it = playerList.begin(); it!= playerList.end();)
		{
			if((*it)->getPlayerId() == id)
			{
				delete *it;
				playerList.erase(it);	
				return;
			}
			else 
				++it;
		}
	}
	void Game::createPlayerRO(Player* p)
	{
		RenderObject* ro = p->getRenderObjcet();
		ro->vbo.push_back(Vertex( vec3f(-8,0,8),vec3f(0,1,0),vec4f(),vec2f(0,0)));
		ro->vbo.push_back(Vertex( vec3f(8,0,8),vec3f(0,1,0),vec4f(),vec2f(1,0)));
		ro->vbo.push_back(Vertex( vec3f(8,0,-8),vec3f(0,1,0),vec4f(),vec2f(1,1)));
		ro->vbo.push_back(Vertex( vec3f(-8,0,-8),vec3f(0,1,0),vec4f(),vec2f(0,1)));

		ro->ibo.push_back(0);ro->ibo.push_back(1);ro->ibo.push_back(2);
		ro->ibo.push_back(2);ro->ibo.push_back(3);ro->ibo.push_back(0);

		ro->shader = shaderMgr->loadShader(L"Shader\\general");
			 
		Shader* sd = ShaderManager::getInstancePtr()->getShaderByIdx(ro->shader);
		sd->addAttributes(POS,3,NBE_FLOAT);
		sd->addAttributes(TEXCOORD0,2,NBE_FLOAT);
		sd->addAttributes(NORMAL,3,NBE_FLOAT);
		sd->addAttributes(COLOR,4,NBE_FLOAT);


		ro->texId = textureMgr->LoadFromFile(L"Resources\\player.png")->textureIdx;
		
		m_pRenderer->createVBO(ro,sizeof(Vertex),ro->shader,"PTNC");
		m_pRenderer->createIBO(ro);

	}
	void Game::creaetBulletRO(Bullet* b)
	{
		RenderObject* ro = b->getRenderObjcet();
		
		ro->vbo.push_back(Vertex( vec3f(-8,0,8),vec3f(0,1,0),vec4f(),vec2f(0,0)));
		ro->vbo.push_back(Vertex( vec3f(8,0,8),vec3f(0,1,0),vec4f(),vec2f(1,0)));
		ro->vbo.push_back(Vertex( vec3f(8,0,-8),vec3f(0,1,0),vec4f(),vec2f(1,1)));
		ro->vbo.push_back(Vertex( vec3f(-8,0,-8),vec3f(0,1,0),vec4f(),vec2f(0,1)));

		ro->ibo.push_back(0);ro->ibo.push_back(1);ro->ibo.push_back(2);
		ro->ibo.push_back(2);ro->ibo.push_back(3);ro->ibo.push_back(0);

		ro->shader = generalShader;//shaderMgr->loadShader(L"Shader\\general");
			 
		//Shader* sd = ShaderManager::getInstancePtr()->getShaderByIdx(ro->shader);
		//sd->addAttributes(POS,3,NBE_FLOAT);
		//sd->addAttributes(TEXCOORD0,2,NBE_FLOAT);
		//sd->addAttributes(NORMAL,3,NBE_FLOAT);
		//sd->addAttributes(COLOR,4,NBE_FLOAT);


		ro->texId = textureMgr->LoadFromFile(L"Resources\\character.jpg")->textureIdx;
		
		m_pRenderer->createVBO(ro,sizeof(Vertex),ro->shader,"PTNC");
		m_pRenderer->createIBO(ro);
	}
	void Game::checkHeartBeat()
	{
		SMsg msg;
		if(NeedToSend.size() == 0)
		{
			msg.msgId = HEARTBEAT;			
			msg.sessionId = sessionId;
			NeedToSend.push_back(msg);
		}
	}
	void Game::shoot(Player* p)
	{
		vec3f vel = 10* p->getDir(); 
		BulletInfo info= BulletInfo(p->getPlayerInfo(), (float*)&vel);
		//bulletList.push_back(b);

		SMsg msg;
		msg.msgId = PLAYERSHOOT;
		msg.sessionId = sessionId;
		msg.dataSize = sizeof(BulletInfo);
		memcpy_s(msg.data,sizeof(BulletInfo),&info,sizeof(BulletInfo));
		msg.guarantee = true;
		msg.msgOrder = ++localGuarantee;
		NeedToSend_Guarantee.push_back(msg);
		GuaranteeSendFlag = true;

	}
	void Game::addBullet(BulletInfo* binfo)
	{
		Bullet* oneBullet = new Bullet(binfo);
		for(auto it = bulletList.begin(); it!= bulletList.end(); ++it)
		{
			if(binfo->bulletId == (*it)->getBulletInfo()->bulletId)
				return;
		}

		creaetBulletRO(oneBullet);
		bulletList.push_back(oneBullet);
	}

	void Game::removeBullet(BulletInfo* binfo)
	{
		for(auto it = bulletList.begin(); it!= bulletList.end(); ++it)
		{
			if(binfo->bulletId == (*it)->getBulletInfo()->bulletId)
			{
				delete *it;
				it = bulletList.erase(it);
				return;
			}
		}
	}
}